﻿using System;
using System.Configuration;
using System.Data.Entity.Core;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;
using LsTool;
using LsTool.ApiModels;
using Newtonsoft.Json;
using Zapi.Log.Db;

namespace Zapi.Api.Filters
{
    /// <summary>
    /// 异常处理
    /// </summary>
    public class ErrorFilterAttribute : ExceptionFilterAttribute
    {
        private string _stackTrace;
        private string _msg;
        private string _reModel;
        private string _code;
        async public override Task OnExceptionAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
        {
            Exception exception = actionExecutedContext.Exception;
            _msg = string.Empty;
            _stackTrace = exception.StackTrace;


            _code = ((int)(actionExecutedContext?.ActionContext?.Response?.StatusCode ?? HttpStatusCode.InternalServerError)).ToString();
            if (exception is DbEntityValidationException)
            {
                var ex = (DbEntityValidationException)exception;

                foreach (var result in ex.EntityValidationErrors)
                {
                    foreach (var error in result.ValidationErrors)
                    {
                        _msg += error.ErrorMessage + "\r";
                    }
                }

            }
            else if (exception is DbUpdateException)
            {
                var ex = (DbUpdateException)exception;
                if (ex.InnerException?.InnerException != null) _msg = ex.InnerException?.InnerException.Message;
            }
            else if (exception is EntityException)
            {
                var ex = (EntityException)exception;
                if (ex.InnerException != null)
                {
                    _msg = ex.InnerException.Message;
                }
            }
            else
            if (exception is MyError)
            {
                MyError me = exception as MyError;
                _msg = me.Msg;
                _code = me.Code;
            }
            else
            {
                _msg = exception.Message;
            }
            _reModel = JsonConvert.SerializeObject(new ErrorOut($"{_msg}") { Code = _code });
            actionExecutedContext.Response = new MyMessage(_reModel);


            Setlog(actionExecutedContext);
        }

        private void Setlog(HttpActionExecutedContext actionExecutedContext)
        {
            LogsEf db = new LogsEf();
            var apiLogs = new ApiLogs();
            apiLogs.CreateTime = DateTime.Now;
            apiLogs.AppAliasName = ConfigurationManager.AppSettings["AppAliasName"];
            apiLogs.AppName = actionExecutedContext.Request.RequestUri?.Host;
            apiLogs.Request = JsonConvert.SerializeObject(actionExecutedContext.ActionContext.ActionArguments);
            apiLogs.Response = _reModel;
            apiLogs.Url = actionExecutedContext.Request.RequestUri?.AbsoluteUri;
            apiLogs.Method = actionExecutedContext.Request.Method.ToString();
            apiLogs.StackTrace = _stackTrace;
            apiLogs.StatusCode = _code;

            db.ApiLogs.Add(apiLogs);
            try
            {
                db.SaveChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}